home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-07-27 | 10.9 KB | 390 lines | [TEXT/MMCC] |
- /*================================================================================
- FutureShock
-
- ©1994 Greg Anderson
- greggor@apple.com
-
- A program that uses the Futures package
- ================================================================================*/
- #include <GestaltEqu.h>
- #include <Palettes.h>
-
- #include "Main.h"
- #include "FutureShockDialog.h"
- #include "AppleEventHandlers.h"
-
- #include "MenuHandler.h"
- #include "EventHandler.h"
-
- #include "MacUtilities.h"
- #include "DialogUtilities.h"
- #include "AppleEventUtilities.h"
- #include "Exceptions.h"
- #include "Futures.h"
- #include <AEObjects.h>
-
- //
- // Prototypes for private functions:
- //
- void InitAll(void);
- pascal OSErr QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon);
- pascal OSErr ThreadCreateHandler(ThreadEntryProcPtr threadEntry, void *threadParam, long handlerRefCon, ThreadID *threadMade);
-
- //
- // Globals defined in this file:
- //
- Rect gUniverseRect;
- RgnHandle gUniverseRgn = nil;
- RgnHandle gScratchRgn = nil;
- GrafPtr gWindowMgrPort = nil;
-
- SysEnvRec gThisMacintosh;
- Boolean gHasAppleEvents;
- Boolean gApplicationShouldQuit = false;
-
- #if USESROUTINEDESCRIPTORS
- static RoutineDescriptor gQuitApplicationHandlerRD = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, QuitApplicationEvent);
- #endif
-
- Boolean gHasIdleUpdate = false;
- Str255 gAppName;
-
-
- //----------------------------------------------------------------------------------------
- // main:
- //----------------------------------------------------------------------------------------
- void main()
- {
- RgnHandle mouseRegion;
- AppFile theFile;
- DialogPtr splash;
- short preLoadFiles;
- short message;
- short i;
- OSErr err = noErr;
-
- //
- // Initialize all of the ToolBox managers, change the cursor
- // shape to a watch and display the splash screen.
- //
- InitAll();
- ChangeCursor( watchCursor );
- SetupMenuBar(1001, 1002);
-
- /*
- // Schlep together our command table
- //
- // (command ID, menu ID, item #)
- */
- AddItemIDtoTable( 1, 2, 3 );
- AddItemIDtoTable( 2, 2, 1 );
-
- //
- // Before any threads are created, make sure that the main thread
- // gets swap in and swap out context switch messages
- //
- ThreadCreateNotifyHandler(kApplicationThreadID, 0);
-
- //
- // Call InitFutures declaring that we would like the
- // Futures package to make a thread for IdleFutures,
- // and that it should create a new thread every time
- // AEProcessAppleEvent dispatches an event. Also,
- // give InitFutures a UPP to our thread create notify
- // handler.
- //
- // Every high-level-event-aware application needs a
- // quit-application handler; otherwise, it won't quit
- // when the machine is shut down (for example)
- //
- #if USESROUTINEDESCRIPTORS
- AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, &gQuitApplicationHandlerRD, 0, false);
- #else
- AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, (AEEventHandlerProcPtr) &QuitApplicationEvent, 0, false);
- #endif
- InitFutures(ThreadCreateHandler);
-
- InstallAppleEventHandlers();
- AEObjectInit();
-
- //
- // Ask the process manager what our name is
- //
- ProcessInfoRec theProc;
- ProcessSerialNumber myPSN;
- GetCurrentProcess(&myPSN);
- theProc.processInfoLength = sizeof(ProcessInfoRec);
- theProc.processName = gAppName;
- theProc.processAppSpec = nil;
- theProc.processLocation = nil;
- FailErr(GetProcessInformation(&myPSN, &theProc));
-
- //
- // Set the cursor back to an arrow
- //
- InitCursor();
-
- //
- // Set up the initial mouse region
- //
- mouseRegion = NewRgn();
-
- long powerMgrResult;
- if((Gestalt(gestaltPowerMgrAttr, &powerMgrResult) == noErr) && ((powerMgrResult & (1 << gestaltPMgrCPUIdle)) != 0))
- gHasIdleUpdate = true;
-
- //
- // Set up a failure handler for failures that are not
- // trapped elsewhere
- //
- Try
- {
- //
- // When the program begins, open our dialog box.
- // If the dialog is ever closed, we will quit (DA model)
- //
- OpenFutureShockDialog();
-
- //
- // Live here until the 'gApplicationShouldQuit' flag
- // becomes true
- //
- while(gApplicationShouldQuit == false)
- HandleEvents(mouseRegion);
- }
- Catch(err)
- {
- //
- // We don't expect to ever get here...
- //
- }
-
- // DebugStr("\pAbout to quit!");
- } // main
-
- //----------------------------------------------------------------------------------------
- // InitAll:
- //
- // Initialize various Macintosh managers
- //----------------------------------------------------------------------------------------
- void InitAll()
- {
- OSErr theErr;
- long heapSpace;
- Ptr appLimit;
- THz appBase;
- long gestaltResult;
- short callsToMoreMasters = 10;
-
- appBase = ApplicZone();
- appLimit = GetApplLimit();
- heapSpace = FreeMem();
- MaxApplZone();
- appLimit = GetApplLimit();
- heapSpace = FreeMem();
- while( callsToMoreMasters-- )
- MoreMasters();
-
- InitGraf(&qd.thePort);
- InitFonts();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
-
- //
- // Get the SysEnvirons record
- //
- SysEnvirons( 1, &gThisMacintosh );
-
- //
- // Check to see if AppleEvents are available
- //
- theErr = Gestalt( gestaltAppleEventsAttr, &gestaltResult );
- gHasAppleEvents = ( (theErr == noErr) && ((gestaltResult & (1L << gestaltAppleEventsPresent)) != 0) );
-
- //
- // Set a global rectangle to hold the extent of QuickDraw workspace
- // (Note: QuickDraw coordinates range from +-32767, but there
- // are bugs in QuickDraw that make it inadvisable to go beyond
- // +-16000 or so.)
- //
- SetRect(&gUniverseRect,-16000,-16000,16000,16000);
- gUniverseRgn = NewRgn();
- RectRgn(gUniverseRgn, &gUniverseRect);
- gScratchRgn = NewRgn();
- GetPort(&gWindowMgrPort);
- } // InitAll
-
- //----------------------------------------------------------------------------------------
- // ExitProgram:
- //----------------------------------------------------------------------------------------
- OSErr ExitProgram(CWindowPtr window, short item)
- {
- //
- // A "real" program would try to close all of its windows
- // first (give the user a chance to cancel)
- //
- gApplicationShouldQuit = true;
-
- return noErr;
- } // ExitProgram
-
- //----------------------------------------------------------------------------------------
- // QuitApplicationEvent:
- //----------------------------------------------------------------------------------------
- pascal OSErr QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon)
- {
- //
- // You should never call ExitToShell from an AppleEvent handler
- //
- gApplicationShouldQuit = true;
-
- return noErr;
- }
-
- extern TException* gExceptionStack;
-
- #if __MWERKS__
- extern void* __local_destructor_chain;
- #endif
-
- class TThreadContext
- {
- public:
- TThreadContext(long threadCreateRefcon) :
- #if __MWERKS__
- fLocalDestructorChain(nil),
- #endif
- fThreadCreateRefcon(threadCreateRefcon),
- fExceptionStack(nil)
- {};
-
- void SwapIn(ThreadID);
- void SwapOut(ThreadID);
- void DisposeContext(ThreadID);
-
- long ThreadCreateRefcon() const { return fThreadCreateRefcon; }
-
- private:
-
- #if __MWERKS__
- void* fLocalDestructorChain;
- #endif
- const long fThreadCreateRefcon;
- TException* fExceptionStack;
- };
-
- //----------------------------------------------------------------------------------------
- // TThreadContext::SwapIn
- //----------------------------------------------------------------------------------------
- void TThreadContext::SwapIn(ThreadID threadID)
- {
- gExceptionStack = fExceptionStack;
- #if __MWERKS__
- __local_destructor_chain = fLocalDestructorChain;
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // TThreadContext::SwapOut
- //----------------------------------------------------------------------------------------
- void TThreadContext::SwapOut(ThreadID threadID)
- {
- fExceptionStack = gExceptionStack;
- #if __MWERKS__
- fLocalDestructorChain = __local_destructor_chain;
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // TThreadContext::DisposeContext
- //----------------------------------------------------------------------------------------
- void TThreadContext::DisposeContext(ThreadID threadID)
- {
- delete this;
- }
-
- //----------------------------------------------------------------------------------------
- // SwapThreadContextIn
- //----------------------------------------------------------------------------------------
- pascal void SwapThreadContextIn(ThreadID thread, void* refCon)
- {
- TThreadContext* threadContext = (TThreadContext*) refCon;
- threadContext->SwapIn(thread);
- }
-
- //----------------------------------------------------------------------------------------
- // SwapThreadContextOut
- //----------------------------------------------------------------------------------------
- pascal void SwapThreadContextOut(ThreadID thread, void* refCon)
- {
- TThreadContext* threadContext = (TThreadContext*) refCon;
- threadContext->SwapOut(thread);
- }
-
- //----------------------------------------------------------------------------------------
- // DestroyThreadContext
- //----------------------------------------------------------------------------------------
- pascal void DestroyThreadContext(ThreadID thread, void* refCon)
- {
- TThreadContext* threadContext = (TThreadContext*) refCon;
- threadContext->DisposeContext(thread);
- }
-
- //----------------------------------------------------------------------------------------
- // ThreadCreateNotifyHandler
- //----------------------------------------------------------------------------------------
- pascal OSErr ThreadCreateNotifyHandler(ThreadID createdThread, long threadCreateRefcon)
- {
- TThreadContext* threadContext = new TThreadContext(threadCreateRefcon);
-
- SetThreadSwitcher(createdThread, SwapThreadContextIn, (void*) threadContext, true);
- SetThreadSwitcher(createdThread, SwapThreadContextOut, (void*) threadContext, false);
- SetThreadTerminator(createdThread, DestroyThreadContext, (void*) threadContext);
-
- return noErr;
- }
-
- //----------------------------------------------------------------------------------------
- // NewThreadWithNotification
- //
- // This routine calls 'NewThread', then notifies the application of what it has done
- //----------------------------------------------------------------------------------------
- OSErr NewThreadWithNotification(ThreadStyle threadStyle, ThreadEntryProcPtr threadEntry, void *threadParam, Size stackSize, ThreadOptions options, void **threadResult, ThreadID *threadMade, long threadCreateRefcon)
- {
- OSErr err = noErr;
-
- err = NewThread(threadStyle, threadEntry, threadParam, stackSize, options, threadResult, threadMade);
- if(err == noErr)
- err = ThreadCreateNotifyHandler(*threadMade, threadCreateRefcon);
-
- return err;
- }
-
- //----------------------------------------------------------------------------------------
- // ThreadCreateHandler
- //----------------------------------------------------------------------------------------
- pascal OSErr ThreadCreateHandler(ThreadEntryProcPtr threadEntry, void *threadParam, long handlerRefCon, ThreadID *threadMade)
- {
- Size stackSize = 0;
- ThreadOptions options = kCreateIfNeeded | kFPUNotNeeded;
-
- OSErr theErr = NewThread(
- kCooperativeThread,
- threadEntry,
- threadParam,
- stackSize,
- options,
- nil,
- threadMade);
-
- if(theErr == noErr)
- theErr = ThreadCreateNotifyHandler(*threadMade, handlerRefCon);
-
- return theErr;
- }
-
-
-